home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / pascal / tp_asm.exe / TP&ASM.OOP < prev    next >
Encoding:
Text File  |  1989-07-31  |  22.1 KB  |  648 lines

  1.  
  2.   TP&Asm           Integrated Compile-Time Assembler          Version 2.2
  3.  
  4.                 Copyright (c) 1989  Richard W. Prescott
  5.                           All Rights Reserved
  6.  
  7. ═══════ Built-In Assembly Language Support for Turbo Pascal Compilers ═══════
  8.  
  9.  All brand and product names mentioned herein are trademarks or registered
  10.                 trademarks of their respective holders.
  11.  
  12.   ┌─────────────────────────────────────────────────────────────────────┐
  13.   │ This file contains detailed reference information to enable you to  │
  14.   │ make effective use of the TP&Asm assembly environment.  For general │
  15.   │ information on getting started please see the README file.          │
  16.   └─────────────────────────────────────────────────────────────────────┘
  17.  
  18. This file contains information specific to the use of TP&Asm with 
  19. Turbo Pascal 5.5 Objects and Methods.  It is intended to supplement 
  20. the information contained in the files TP&ASM.REF and TP&ASM2.REF.
  21.  
  22.  
  23. Turbo Pascal Version 5.5 extends Turbo Pascal through the addition 
  24. of the Object Oriented Programming (OOP) concepts of "Objects" and 
  25. "Methods".  Briefly, an "Object" is a structured type which extends 
  26. the concept of a Record, while a "Method" is a procedure or function
  27. which is associated with an Object in somewhat the same way as data
  28. components are associated with Records.  It is assumed that the reader 
  29. is familiar with these concepts and has read Chapter 1 of the Version
  30. 5.5 OOP Guide.
  31.  
  32. Please keep in mind the following distinctions:
  33.  
  34.    Objects can be STATIC or DYNAMIC;
  35.      according to whether they are statically defined in a VAR 
  36.      or CONST statement, or dynamically allocated on the Heap;
  37.  
  38.    Methods can be STATIC or VIRTUAL;
  39.      according to whether they are defined "virtual", and
  40.      thereby given an entry in a special structure called 
  41.      the Virtual Method Table (VMT);
  42.  
  43.    Method CALLs can be DIRECT or VIRTUAL;
  44.      according to whether the target address of the call is
  45.      "bound" into a direct call at compile time, or obtained
  46.      from a lookup in the Virtual Method Table at run time.
  47.  
  48. A Virtual method call is actually a standard Far Indirect Call in 
  49. which the DWORD (Pointer) address of the method entry code is found 
  50. in the Virtual Method Table.  It is also possible to make indirect
  51. calls via a standard Pascal Pointer or assembly DWord variable, and
  52. the address to be loaded into the pointer can either be bound at 
  53. compile time or obtained from the VMT mechanism.
  54.  
  55. Note that in both Pascal and assembly language it is possible to 
  56. make DIRECT calls to VIRTUAL methods.
  57.  
  58.  
  59.  
  60. The following topics are described below:
  61.  
  62.   1. Using Assembly Language in Methods
  63.   2. Accessing the Self parameter
  64.   3. Accessing Object data fields
  65.   4. Calling an Object's Methods
  66.   5. TypeOf and SizeOf for an Instance
  67.  
  68.  
  69.  
  70. 1. Using Assembly Language in Methods
  71.  
  72. Version 5.5 permits Methods to be written either entirely in Pascal
  73. or entirely in (External) Assembly language.  TP&Asm provides the
  74. option of writing any portion of a Method in assembly language, 
  75. using the TP&Asm "Assemble" statement.  (A method, procedure, or 
  76. function can have any number of Assemble statements).
  77.  
  78. TP&Asm also provides the "Internal" statement, which can be used to 
  79. write an entire method in assembly using standard External Assembly 
  80. language format.  This section provides examples using the Assemble 
  81. and the Internal statements to implement an entire method in 
  82. assembly language.
  83.  
  84. As a simple example, consider the implementation of an "Area" method 
  85. for the Rect object defined on page 103 of the OOP Guide.  The Rect
  86. data fields are defined to be:
  87.  
  88.                   X1, Y1, X2, Y2: Integer;
  89.  
  90. where (X1,Y1) is the upper left corner and (X2,Y2) is the lower right 
  91. corner.  The Pascal implementation of this method would simply be
  92.  
  93.    Function Rect.Area: Integer;
  94.    BEGIN
  95.      Area := (X2 - X1) * (Y2 - Y1);
  96.    END; 
  97.  
  98. for which the compiler generates the following code:
  99.  
  100.    BEGIN
  101.  
  102.    3F4B:0037 55            PUSH BP           ;Standard Entry Code
  103.    3F4B:0038 89E5          MOV BP,SP
  104.    3F4B:003A B80200        MOV AX,0002
  105.    3F4B:003D 9A4402573F    CALL 3F57:0244
  106.    3F4B:0042 83EC02        SUB SP,+02
  107.    ----
  108.      Area := (X2 - X1) * (Y2 - Y1);
  109.  
  110.    3F4B:0045 C47E06        LES DI,[BP+06]    ;Les Di,Self
  111.    3F4B:0048 26            ES:
  112.    3F4B:0049 8B4506        MOV AX,[DI+06]    :Mov Ax,Es:[Di].Y2
  113.    3F4B:004C C47E06        LES DI,[BP+06]    ;Les Di,Self
  114.    3F4B:004F 26            ES:
  115.    3F4B:0050 2B4502        SUB AX,[DI+02]    ;Sub Ax,Es:[Di].Y1
  116.    3F4B:0053 8BD0          MOV DX,AX
  117.    3F4B:0055 C47E06        LES DI,[BP+06]    ;Les Di,Self
  118.    3F4B:0058 26            ES:
  119.    3F4B:0059 8B4504        MOV AX,[DI+04]    ;Mov Bx,Es:[Di].X2
  120.    3F4B:005C C47E06        LES DI,[BP+06]    ;Les Di,Self
  121.    3F4B:005F 26            ES:
  122.    3F4B:0060 2B05          SUB AX,[DI]       ;Sub Bx,Es:[Di].X1
  123.    3F4B:0062 F7EA          IMUL DX           ;IMul Dx
  124.    3F4B:0064 8946FE        MOV [BP-02],AX    ;Mov Area,Ax
  125.    ----
  126.    END; 
  127.  
  128.    3F4B:0067 8B46FE        MOV AX,[BP-02]    ;Standard Exit Code
  129.    3F4B:006A 89EC          MOV SP,BP
  130.    3F4B:006C 5D            POP BP
  131.    3F4B:006D CA0400        RETF 0004
  132.    ----
  133.  
  134.  
  135. 1.1  Using an Assemble statement
  136.  
  137. The following example illustrates how the "Area" method would be
  138. coded using an Assemble statement.  Note that the fields of Rect 
  139. are accessible by name without any explicit assembly definition
  140. (e.g. STRUC), and that since Es:Di is never altered, it is not 
  141. necessary to reload it before each data access.  Standard entry
  142. and exit code is provided by the compiler.
  143.  
  144.  
  145.    Function Rect.Area: Integer;
  146.    BEGIN            {- Compiler generates standard entry code -}
  147.     Assemble
  148.      Les Di,Self         ;Load Self Pointer
  149.      Mov Ax,Es:[Di].Y2
  150.      Sub Ax,Es:[Di].Y1   ;Compute Y2 - Y1
  151.      Mov Dx,Es:[Di].X2
  152.      Sub Dx,Es:[Di].X1   ;Compute X2 - X1
  153.      IMul Dx             ;Compute product
  154.      Mov Area,Ax         ;put in function result
  155.     End; {Assemble}
  156.    END;             {- Compiler generates standard exit code -}
  157.  
  158.  
  159. 1.2  Using an Internal statement - External Assembly format
  160.  
  161. The following example illustrates how the "Area" method would be
  162. coded using an Internal statement in the full External Assembly 
  163. format.  Note that the fields of Rect are again accessible by 
  164. name without any explicit assembly definition.  As with External
  165. assembly code, entry and exit code must be explicitly provided.
  166.  
  167.  
  168.    Internal RectMethods
  169.  
  170.    CODE    SEGMENT BYTE PUBLIC
  171.  
  172.            ASSUME Cs:CODE
  173.  
  174.            PUBLIC Rect@Area
  175.  
  176.    Rect@Area       PROC    FAR
  177.  
  178.    @Self           EQU     DWORD PTR [bp+6]
  179.  
  180.            Push    Bp             ;Explicit
  181.            Mov     Bp,Sp          ;  Entry Code
  182.  
  183.            Les     Di,@Self       ;Load Self Pointer
  184.            Mov     Ax,Es:[Di].Y2
  185.            Sub     Ax,Es:[Di].Y1  ;Compute Y2 - Y1
  186.            Mov     Dx,Es:[Di].X2
  187.            Sub     Dx,Es:[Di].X1  ;Compute X2 - X1
  188.            IMul    Dx             ;Compute product
  189.  
  190.            Mov     Sp,Bp          ;Explicit     (Function
  191.            Pop     Bp             ;  Exit         Result
  192.            Retf    4              ;    Code      is in Ax)
  193.  
  194.    Rect@Area       ENDP
  195.  
  196.    CODE    ENDS
  197.  
  198.            END
  199.  
  200.  
  201. 1.3  Using an Internal statement - reduced overhead format
  202.  
  203. TP&Asm ignores certain "overhead" statements including "Assume" 
  204. and "Public", and can make its own determination of the proper PROC 
  205. model to use.  The following example illustrates how the "Area" 
  206. method would be coded using an Internal statement with the minimum 
  207. necessary "overhead" statements.  Note that the more readable form
  208. "Rect.Area" is permitted in place of "Rect@Area".
  209.  
  210.  
  211.    Internal RectMethods
  212.    CODE SEGMENT
  213.    Rect.Area PROC
  214.      @Self EQU D[bp+6]
  215.      Push Bp            ;Explicit
  216.      Mov Bp,Sp          ;  Entry Code
  217.      Les Di,@Self       ;Load Self Pointer
  218.      Mov Ax,Es:[Di].Y2
  219.      Sub Ax,Es:[Di].Y1  ;Compute Y2 - Y1
  220.      Mov Dx,Es:[Di].X2
  221.      Sub Dx,Es:[Di].X1  ;Compute X2 - X1
  222.      IMul Dx            ;Compute product
  223.      Mov Sp,Bp          ;Explicit    (Function
  224.      Pop Bp             ;  Exit        Result
  225.      Retf 4             ;    Code     is in Ax)
  226.    Rect.Area ENDP
  227.    CODE    ENDS
  228.    END
  229.  
  230.  
  231. 2. Accessing the Self parameter
  232.  
  233. Every method has an implicit VAR parameter "Self" which possesses
  234. the type of the object whose method is being defined, and which 
  235. contains the address of the instance which generated the method 
  236. call.  This parameter is always the last parameter pushed onto
  237. the stack, and is therefore always located immediately above the
  238. return address (Cs:Ip).
  239.  
  240.  
  241. 2.1  Accessing Self within an Assemble statement
  242.  
  243. Within an Assemble statement the Self parameter to a method is
  244. accessible by name.  The following statement loads the Self 
  245. parameter into Es:Di
  246.  
  247.          Les Di,Self
  248.  
  249. Since the Self parameter is a (DWord) Pointer, an attempt to
  250. reference it as a Byte or Word variable (e.g. "Mov Ax,Self")
  251. will generate a syntax error.  You can override the defined
  252. type of any variable, however, using a data size specifier.
  253. Thus any of the following:
  254.  
  255.          Mov W Ax,Self
  256.          Mov Ax,W Self
  257.          Mov Ax,WORD PTR Self
  258.  
  259. will load into Ax the OFFSET of the instance which generated 
  260. the method call.
  261.  
  262.  
  263. 2.2  Accessing Self within an Internal statement
  264.  
  265. Like External assembly code, Internal assembly code cannot 
  266. reference parameters by name.  References to the Self parameter
  267. must therefore be coded as explicit offsets to a properly
  268. initialized Base or Index register.  The necessary offset will
  269. depend upon the register chosen.
  270.  
  271. Assuming the following entry code:
  272.  
  273.          Push Bp
  274.          Mov Bp,Sp
  275.  
  276. then the Self parameter will be at [Bp+6], and the following 
  277. statement will load it into Es:Di
  278.  
  279.          Les Di,[Bp+6]
  280.  
  281. As an alternative, you can define Self with an EQUate so that
  282. subsequent statements can access it by name:
  283.  
  284.          Self EQU D [Bp+6]
  285.          Les Di,Self
  286.  
  287. (Since Bp references use Ss as the default segment it is not
  288. necessary to code an explicit Ss Override).
  289.  
  290. It is also possible to access Self and other method parameters
  291. using another Index or Base register.  Given the following entry
  292. code:
  293.  
  294.          Mov Bx,Sp
  295.  
  296. then the Self parameter will be at Ss:[Bx+4], and the following 
  297. statement will load it into Es:Di
  298.  
  299.          Les Di,Ss:[Bx+4]
  300.  
  301. Again, you can define Self with an EQUate so that subsequent 
  302. statements can access it by name: 
  303.  
  304.          Self EQU D Ss:[Bx+4]
  305.          Les Di,Self
  306.  
  307. (Since Bx references use Ds as the default segment you must code
  308. an explicit Ss override).
  309.  
  310.  
  311.  
  312. 3. Accessing Object data fields
  313.  
  314. TP&Asm provides the capability of making assembly reference to
  315. Object data fields both from within and from outside its methods.
  316. The examples below assume the following VAR and Type Definitions:
  317.  
  318. TYPE
  319.   RecType = Record
  320.     NestedInteger: Integer;
  321.     NestedPointer: Pointer;
  322.   End;
  323.  
  324.   ObjType = object
  325.     ObjByte:   Byte;
  326.     ObjString: STRING[20];
  327.     ObjRecord: RecType;
  328.     :
  329.   end;
  330.  
  331. VAR
  332.   StaticObjInst: ObjType;
  333.   DynamicObjPtr: ^ObjType;
  334.  
  335.  
  336. 3.1  Accessing an Object's data fields from within its methods
  337.  
  338. Within an object's methods the unqualified reference to an Object
  339. data field represents the offset of that field within the Object
  340. structure.  Access to the Object's data is accomplished by loading
  341. the "Self" pointer into a Segment:Index register pair (typically
  342. Es:Di), and using the field identifier as the offset in an indexed
  343. memory reference:
  344.  
  345.     Les Di,Self
  346.     Es Mov Al,ObjByte[Di]
  347.     Es Lea Di,ObjString[Di]
  348.     Es IMul ObjRecord.NestedInteger[Di]
  349.     Es Les Bx,ObjRecord.NestedPointer[Di]
  350.  
  351. TP&Asm supports numerous other formats for coding indexed memory 
  352. access:
  353.  
  354.     Es Mov Al,[Di].ObjByte
  355.     Es Mov Al,[Di+ObjByte]
  356.     Mov Al,Es:ObjByte[Di]
  357.     Mov Al,Es:[Di].ObjByte
  358.     Mov Al,Es:[Di]ObjByte
  359.     Mov Al,Es:[Di+ObjByte]
  360.     Es: 
  361.     Mov Al,[Di+ObjByte]
  362.  
  363. It is also possible to use a full TypeDef.Component specification 
  364. as is done with Dynamic Object data references (see 3.3):
  365.  
  366.     Es Mov Al,ObjType.ObjByte[Di]
  367.  
  368. Unindexed reference to an Object's data fields is not permitted
  369. unless qualified with the Object Type identifier, in which case
  370. the reference is treated as an immediate data operand equal to
  371. the offset of the field within the Object structure:
  372.  
  373.     Mov Ax,ObjType.ObjString  ; Same as Mov Ax,0001
  374.  
  375.  
  376. 3.2  Accessing STATIC Object data fields from outside its methods
  377.  
  378. Outside an object's methods all references to an Object's data 
  379. fields must be qualified with either the Instance identifier or the 
  380. Object's Type identifier.  Access to a Static Object's data is 
  381. accomplished using a fully qualified name beginning with the
  382. Instance identifier:
  383.  
  384.     Mov Al,StaticObjInst.ObjByte
  385.     Lea Di,StaticObjInst.ObjString
  386.     IMul StaticObjInst.ObjRecord.NestedInteger
  387.     Les Bx,StaticObjInst.ObjRecord.NestedPointer
  388.     Mov Dx,OFFSET StaticObjInst.ObjString
  389.  
  390. Unless preceeded by the keyword "OFFSET", the reference refers
  391. to the contents of the indicated memory address, using the defined 
  392. type of the particular Object field.  (Note: OFFSET is not permitted 
  393. with local variables, which are always referenced relative to [Bp].
  394. Use "Lea Reg,LocalVar" in place of "Mov Reg,OFFSET LocalVar").
  395.  
  396. As noted above, if a reference is qualified with the Object Type 
  397. identifier, it is treated as an immediate data operand equal to
  398. the offset of the field within the Object structure:
  399.  
  400.     Mov Ax,ObjType.ObjString  ; Same as Mov Ax,0001
  401.  
  402.  
  403. 3.3  Accessing DYNAMIC Object data fields from outside its methods
  404.  
  405. Access to a Dynamic Object's data is accomplished by loading the 
  406. pointer variable into a Segment:Index register pair (typically Es:Di), 
  407. and using the field identifier (qualified by the Object's Type 
  408. identifier) as the offset in an indexed memory reference:
  409.  
  410.     Les Di,DynamicObjPtr
  411.     Es Mov Al,ObjType.ObjByte[Di]
  412.     Es Lea Di,ObjType.ObjString[Di]
  413.     Es IMul ObjType.ObjRecord.NestedInteger[Di]
  414.     Es Les Bx,ObjType.ObjRecord.NestedPointer[Di]
  415.  
  416. An indexed reference as shown uses the defined type of the particular
  417. object field.  An unindexed reference is treated as an immediate data 
  418. operand equal to the offset of the field within the Object structure:
  419.  
  420.     Mov Ax,ObjType.ObjString  ; Same as Mov Ax,0001
  421.  
  422.  
  423.  
  424. 4. Calling an Object's Methods
  425.  
  426. Outside an Object's methods, Pascal method calls are always direct 
  427. if the method is static and virtual if the method is virtual.
  428. Within a method, the same strategy is used, except when the method 
  429. call is qualified with the Object Type identifier of the current 
  430. object or an ancestor.  In this latter case a direct call is used 
  431. even if the method is virtual.
  432.  
  433. As shown in the examples below, TP&Asm provides the capability to 
  434. exercise total control over the type of call to use both within and 
  435. outside an Object's methods.  It is not the presence or absence of 
  436. an Object Type qualifier, however, which determines whether a 
  437. virtual or direct call is used - in fact, all assembly language
  438. method calls from outside an object's methods must be qualified 
  439. with the Object Type.  It is the presence or absence of an explicit 
  440. memory operand (typically an index register) which determines 
  441. whether a virtual method identifier is interpreted as the method's 
  442. offset within its VMT, or as the method's actual (static) address.  
  443.  
  444. The examples below assume that ObjType has the following Methods:
  445.  
  446.     PROCEDURE StaticMeth;
  447.     PROCEDURE VirtualMeth; Virtual;
  448.  
  449. It is also assumed that the following Instance and Pointer variable 
  450. have been defined:
  451.  
  452.  VAR
  453.    StaticObjInst: ObjType;
  454.    DynamicObjPtr: ^ObjType;
  455.  
  456.  
  457. 4.1  Calling an Object's Methods from within another method
  458.  
  459. Method calls made from within another method should first push 
  460. any explicit parameters, and then push the current "Self" pointer 
  461. as the Self parameter of the target method.  Calls to static 
  462. methods are always direct, and are made using an unindexed 
  463. reference to the method identifier:
  464.  
  465.     Les Di,Self        ;Load Self pointer
  466.     Push Es,Di         ;Push as Self parameter
  467.     Call StaticMeth    ;Unindexed reference codes direct call
  468.  
  469. The method identifier is interpreted as the (static) address of the 
  470. method code within the current CSeg.  The following "Pas" statement 
  471. is equivalent:
  472.  
  473.     Pas StaticMeth;
  474.  
  475. Direct calls to Virtual methods are made using an unindexed 
  476. reference to the method identifier:
  477.  
  478.     Les Di,Self        ;Load Self pointer
  479.     Push Es,Di         ;Push as Self parameter
  480.     Call VirtualMeth   ;Unindexed reference codes direct call
  481.  
  482. The method identifier is interpreted as the (static) address of the 
  483. method code within the current CSeg.  The following "Pas" statement 
  484. is equivalent:
  485.  
  486.     Pas ObjType.VirtualMeth;
  487.  
  488. Virtual calls to Virtual methods are made using an indexed 
  489. reference to the method identifier, after first loading the DSeg
  490. offset of Self's VMT into the index register:
  491.  
  492.     Les Di,Self          ;Load Self pointer
  493.     Push Es,Di           ;Push as Self parameter
  494.     Es Mov Di,VMT[Di]    ;Load VMT offset into Di
  495.     Call VirtualMeth[Di] ;Indexed reference codes virtual call
  496.  
  497. The method identifier is interpreted as the offset within the VMT of 
  498. the method's VMT entry.  The following "Pas" statement is equivalent:
  499.  
  500.     Pas VirtualMeth;
  501.  
  502.  
  503.  
  504. 4.2  Calling a STATIC Object's Methods from outside its methods
  505.  
  506. Method calls made from outside a STATIC Object's methods should 
  507. first push any explicit parameters, and then push the static 
  508. address of the current instance as the Self parameter of the 
  509. target method.  All method identifiers and all references to the
  510. symbol "VMT" must be qualified with an Object Type identifier.
  511.  
  512. Calls to static methods are always direct, and are made using an 
  513. unindexed reference to the method identifier:
  514.  
  515.     Lea Di,StaticObjInst     ;Load offset of Instance into Di
  516.     Push Ds,Di               ;Push Ss,Di for a Local Var Instance
  517.     Call ObjType.StaticMeth  ;Unindexed ref codes direct call
  518.  
  519. The method identifier is interpreted as the (static) address of the 
  520. method code within the current CSeg.  The following "Pas" statement 
  521. is equivalent:
  522.  
  523.     Pas StaticObjInst.StaticMeth;
  524.  
  525. Direct calls to Virtual methods are made using an unindexed 
  526. reference to the method identifier:
  527.  
  528.     Lea Di,StaticObjInst     ;Load offset of Instance into Di
  529.     Push Ds,Di               ;Push Ss,Di for a Local Var Instance
  530.     Call ObjType.VirtualMeth ;Unindexed ref codes direct call
  531.  
  532. The method identifier is interpreted as the (static) address of 
  533. the method code within the current CSeg.  There is no Pascal 
  534. equivalent. 
  535.  
  536. Virtual calls to Virtual methods are made using an indexed 
  537. reference to the method identifier, after first loading the DSeg
  538. offset of the Object Type's VMT into the index register:
  539.  
  540.     Lea Di,StaticObjInst     ;Load offset of Instance into Di
  541.     Push Ds,Di               ;Push Ss,Di for a Local Var Instance
  542.     Mov Di,ObjType.VMT[Di]   ;Load VMT offset into Di
  543.     Call ObjType.VirtualMeth[Di] ;Indexed ref codes virtual call
  544.  
  545. The method identifier is interpreted as the offset within the VMT of 
  546. the method's VMT entry.  The following "Pas" statement is equivalent:
  547.  
  548.     Pas StaticObjInst.VirtualMeth;
  549.  
  550.  
  551. 4.3  Calling a DYNAMIC Object's Methods from outside its methods
  552.  
  553. Method calls made from outside a DYNAMIC Object's methods should 
  554. first push any explicit parameters, and then push the dynamic
  555. pointer variable for the current instance as the Self parameter 
  556. of the target method.  All method identifiers and all references 
  557. to the symbol "VMT" must be qualified with an Object Type 
  558. identifier.
  559.  
  560. Calls to static methods are always direct, and are made using an 
  561. unindexed reference to the method identifier:
  562.  
  563.     Les Di,DynamicObjPtr     ;Load Pointer into Es:Di
  564.     Push Es,Di               ;Push as "Self" parameter
  565.     Call ObjType.StaticMeth  ;Unindexed ref codes direct call
  566.  
  567. The method identifier is interpreted as the (static) address of the 
  568. method code within the current CSeg.  The following "Pas" statement 
  569. is equivalent:
  570.  
  571.     Pas DynamicObjPtr^.StaticMeth;
  572.  
  573. Direct calls to Virtual methods are made using an unindexed 
  574. reference to the method identifier:
  575.  
  576.     Les Di,DynamicObjPtr     ;Load Pointer into Es:Di
  577.     Push Es,Di               ;Push as "Self" parameter
  578.     Call ObjType.VirtualMeth ;Unindexed ref codes direct call
  579.  
  580. The method identifier is interpreted as the (static) address of 
  581. the method code within the current CSeg.  There is no Pascal 
  582. equivalent. 
  583.  
  584. Virtual calls to Virtual methods are made using an indexed 
  585. reference to the method identifier, after first loading the DSeg
  586. offset of the Object Type's VMT into the index register:
  587.  
  588.     Les Di,DynamicObjPtr     ;Load Pointer into Es:Di
  589.     Push Es,Di               ;Push as "Self" parameter
  590.     Mov Di,ObjType.VMT[Di]   ;Load VMT offset into Di
  591.     Call ObjType.VirtualMeth[Di] ;Indexed ref codes virtual call
  592.  
  593. The method identifier is interpreted as the offset within the VMT of 
  594. the method's VMT entry.  The following "Pas" statement is equivalent:
  595.  
  596.     Pas DynamicObjPtr^.VirtualMeth;
  597.  
  598.  
  599.  
  600. 5. TypeOf and SizeOf for an Instance
  601.  
  602.  
  603. 5.1  TypeOf and SizeOf within a method
  604.  
  605. The following code will set Dx:Ax to TypeOf(Self)
  606.  
  607.   Les Di,Self
  608.   Es Mov Ax,ObjType.VMT[Di]
  609.   Mov Dx,Ds
  610.  
  611. The following code will set Ax to SizeOf(Self)
  612.  
  613.   Les Di,Self
  614.   Es Mov Di,ObjType.VMT[Di]
  615.   Mov Ax,[Di]
  616.  
  617.  
  618. 5.2  TypeOf and SizeOf for a STATIC Object instance
  619.  
  620. The following code will set Dx:Ax to TypeOf(StaticObjInst)
  621.  
  622.   Lea Di,StaticObjInst
  623.   Mov Ax,ObjType.VMT[Di]
  624.   Mov Dx,Ds
  625.  
  626. The following code will set Ax to SizeOf(StaticObjInst)
  627.  
  628.   Lea Di,StaticObjInst
  629.   Mov Di,ObjType.VMT[Di]
  630.   Mov Ax,[Di]
  631.  
  632.  
  633.  
  634. 5.3  TypeOf and SizeOf for a DYNAMIC Object instance
  635.  
  636. The following code will set Dx:Ax to TypeOf(DynamicObjPtr^)
  637.  
  638.   Les Di,DynamicObjPtr
  639.   Es Mov Ax,ObjType.VMT[Di]
  640.   Mov Dx,Ds
  641.  
  642. The following code will set Dx:Ax to SizeOf(DynamicObjPtr^)
  643.  
  644.   Les Di,DynamicObjPtr
  645.   Es Mov Di,ObjType.VMT[Di]
  646.   Mov Ax,[Di]
  647.  
  648.